﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Threading;



namespace Command
{

    public class PushToDBService : IPushToDBService
	{
        public CreateCurrencyResponse CreateCurrency(CreateCurrencyRequest request)
        {
            CreateCurrencyResponse RateResponse = new CreateCurrencyResponse();

            try
            {
                using (ExtRatesEntities context = new ExtRatesEntities())
                {
                    Currency CurrencyTemp = new Currency()
                    {
                        Name = request.Name
                    };
                    context.AddToCurrency(CurrencyTemp);
                    context.SaveChanges();
                }
            }
            catch (Exception e)
            {
                RateResponse.Status = ResponseStatus.Error;
            }

            return RateResponse;
        }

        public CreateRateResponse CreateRate(CreateRateRequest request)
        {
            CreateRateResponse RateResponse = new CreateRateResponse();

            try
            {
                using (ExtRatesEntities context = new ExtRatesEntities())
                {
                    Currency CurrencyTemp = context.Currency.Where(c => c.Name == request.CurrencyName).FirstOrDefault();
                    if (CurrencyTemp == null)
                    {
                        CurrencyTemp = new Currency()
                        {
                            Name = request.CurrencyName
                        };

                        context.AddToCurrency(CurrencyTemp);
                        context.SaveChanges();
                    }

                    Period PeriodTemp = context.Period.Where(c => c.DateTime == request.Period).FirstOrDefault();
                    if (PeriodTemp == null)
                    {
                        PeriodTemp = new Period()
                        {
                            DateTime = request.Period
                        };

                        context.AddToPeriod(PeriodTemp);
                        context.SaveChanges();
                    }

                    CurrencyRate CurrencyRateTemp = new CurrencyRate()
                    {
                        Value = request.Value,
                        Period = PeriodTemp,
                        Currency = CurrencyTemp
                    };
                    context.AddToCurrencyRate(CurrencyRateTemp);
                    context.SaveChanges();
                }

                RateResponse.Status = ResponseStatus.OK;
            }
            catch (Exception e)
            {
                RateResponse.Status = ResponseStatus.Error;
            }

            return RateResponse;
        }

        public string AddCurencyRate(CreateRateRequest CreateRateRequestTemp)
        {
            string Response = CreateRate(CreateRateRequestTemp).Status.ToString();

            Thread WriteCache_Thread = new Thread(delegate() { WriteCache(CreateRateRequestTemp); });
            WriteCache_Thread.Start();

            return Response;
        }

        void WriteCache(CreateRateRequest CreateRateRequestTemp)
        {
            UpdateDay(CreateRateRequestTemp);
            UpdateWeek(CreateRateRequestTemp);
            UpdateMonth(CreateRateRequestTemp);
            UpdateYear(CreateRateRequestTemp);
        }

        private void UpdateDay(CreateRateRequest CreateRateRequestTemp)
        {
            using (ExtRatesEntities context = new ExtRatesEntities())
            {
                DateTime Date_Temp = CreateRateRequestTemp.Period;
                DateTime DateBegin_Temp = Date_Temp;
                DateTime DateEnd_Temp = Date_Temp.AddDays(1);
                Currency Currancy_Temp = context.Currency.Where(c => c.Name == CreateRateRequestTemp.CurrencyName).FirstOrDefault();

                //delete from DB
                List<cache_Day> cache_DayList_Temp = context.cache_Day.Where(c => c.Period < DateEnd_Temp && c.Period >= DateBegin_Temp && c.CurrencyID == Currancy_Temp.ID).ToList();

                if (cache_DayList_Temp != null)
                {
                    foreach (cache_Day cache_Day_Temp in cache_DayList_Temp)
                    {
                        context.DeleteObject(cache_Day_Temp);
                        context.SaveChanges();
                    }
                }

                //add to DB
                int iFrequency = 10;
                List<CurrencyRate> CurrencyRateList_Temp = context.CurrencyRate.Where(c => c.Period.DateTime <= DateEnd_Temp && c.Period.DateTime >= DateBegin_Temp && c.Currency.ID == Currancy_Temp.ID).ToList();
                if (CurrencyRateList_Temp.Count < iFrequency)
                    iFrequency = CurrencyRateList_Temp.Count;
                double Koeficient = (double)CurrencyRateList_Temp.Count / iFrequency;

                double MediumGlobal = 0;
                double MaxGlobal = 0;
                double MinGlobal = double.MaxValue;
                for (int Part = 0; Part < iFrequency; Part++)
                {
                    //calc medium, max, min
                    double Medium = 0;
                    for (int k = Convert.ToInt32(Math.Truncate(Part * Koeficient)); k < Convert.ToInt32(Math.Truncate((Part + 1) * Koeficient)); k++)
                    {
                        Medium += CurrencyRateList_Temp[k].Value;
                        MediumGlobal += CurrencyRateList_Temp[k].Value;
                        if (CurrencyRateList_Temp[k].Value > MaxGlobal)
                            MaxGlobal = CurrencyRateList_Temp[k].Value;
                        if (CurrencyRateList_Temp[k].Value < MinGlobal)
                            MinGlobal = CurrencyRateList_Temp[k].Value;
                    }
                    Medium = Medium / (Convert.ToInt32(Math.Truncate((Part + 1) * Koeficient)) - Convert.ToInt32(Math.Truncate(Part * Koeficient)));

                    //add to cache_Day
                    cache_Day cache_Day_Temp = new cache_Day()
                    {
                        Period = Date_Temp,
                        CurrencyID = Currancy_Temp.ID,
                        Value = Medium
                    };
                    context.AddTocache_Day(cache_Day_Temp);
                    context.SaveChanges();
                }
                MediumGlobal /= CurrencyRateList_Temp.Count;

                AdditionalUpdate("day", "medium", MediumGlobal, Currancy_Temp.ID);
                AdditionalUpdate("day", "max", MaxGlobal, Currancy_Temp.ID);
                AdditionalUpdate("day", "min", MinGlobal, Currancy_Temp.ID);

            }
        }

        private void UpdateWeek(CreateRateRequest CreateRateRequestTemp)
        {
            DateTime Date_Temp = CreateRateRequestTemp.Period;

            //delete old by "DateTemp"
            //add new
        }

        private void UpdateMonth(CreateRateRequest CreateRateRequestTemp)
        {
            using (ExtRatesEntities context = new ExtRatesEntities())
            {
                DateTime Date_Temp = CreateRateRequestTemp.Period;
                DateTime DateBegin_Temp = new DateTime(Date_Temp.Year, Date_Temp.Month, 1);
                DateTime DateEnd_Temp = new DateTime(Date_Temp.Year, Date_Temp.Month, 1).AddMonths(1);
                Currency Currancy_Temp = context.Currency.Where(c => c.Name == CreateRateRequestTemp.CurrencyName).FirstOrDefault();

                //delete from DB
                List<cache_Month> cache_DayList_Temp = context.cache_Month.Where(c => c.Period < DateEnd_Temp && c.Period >= DateBegin_Temp && c.CurrencyID == Currancy_Temp.ID).ToList();

                if (cache_DayList_Temp != null)
                {
                    foreach (cache_Month cache_Month_Temp in cache_DayList_Temp)
                    {
                        context.DeleteObject(cache_Month_Temp);
                        context.SaveChanges();
                    }
                }

                //add to DB
                int iFrequency = 10;
                List<CurrencyRate> CurrencyRateList_Temp = context.CurrencyRate.Where(c => c.Period.DateTime <= DateEnd_Temp && c.Period.DateTime >= DateBegin_Temp && c.Currency.ID == Currancy_Temp.ID).ToList();
                if (CurrencyRateList_Temp.Count < iFrequency)
                    iFrequency = CurrencyRateList_Temp.Count;
                double Koeficient = (double)CurrencyRateList_Temp.Count / iFrequency;

                double MediumGlobal = 0;
                double MaxGlobal = 0;
                double MinGlobal = double.MaxValue;
                for (int Part = 0; Part < iFrequency; Part++)
                {
                    //calc medium, max, min
                    double Medium = 0;
                    for (int k = Convert.ToInt32(Math.Truncate(Part * Koeficient)); k < Convert.ToInt32(Math.Truncate((Part + 1) * Koeficient)); k++)
                    {
                        Medium += CurrencyRateList_Temp[k].Value;
                        MediumGlobal += CurrencyRateList_Temp[k].Value;
                        if (CurrencyRateList_Temp[k].Value > MaxGlobal)
                            MaxGlobal = CurrencyRateList_Temp[k].Value;
                        if (CurrencyRateList_Temp[k].Value < MinGlobal)
                            MinGlobal = CurrencyRateList_Temp[k].Value;
                    }
                    Medium = Medium / (Convert.ToInt32(Math.Truncate((Part + 1) * Koeficient)) - Convert.ToInt32(Math.Truncate(Part * Koeficient)));

                    //add to cache_Month
                    cache_Month cache_Month_Temp = new cache_Month()
                    {
                        Period = Date_Temp,
                        CurrencyID = Currancy_Temp.ID,
                        Value = Medium
                    };
                    context.AddTocache_Month(cache_Month_Temp);
                    context.SaveChanges();
                }
                MediumGlobal /= CurrencyRateList_Temp.Count;

                AdditionalUpdate("month", "medium", MediumGlobal, Currancy_Temp.ID);
                AdditionalUpdate("month", "max", MaxGlobal, Currancy_Temp.ID);
                AdditionalUpdate("month", "min", MinGlobal, Currancy_Temp.ID);
            }
        }

        private void UpdateYear(CreateRateRequest CreateRateRequestTemp)
        {
            DateTime Date_Temp = CreateRateRequestTemp.Period;

            //delete old by "DateTemp"
            //add new
        }

        private void AdditionalUpdate(string TableName_Temp, string Type_Temp, double Value_Temp, int CurrancyId_Temp)
        {
            using (ExtRatesEntities context = new ExtRatesEntities())
            {
                Additional AdditionalMed_Temp = context.Additional.Where(c => c.TableName == TableName_Temp && c.Type == Type_Temp && c.CurrencyID == CurrancyId_Temp).FirstOrDefault();
                if (AdditionalMed_Temp != null)
                {
                    context.DeleteObject(AdditionalMed_Temp);
                    context.SaveChanges();
                }
                Additional AdditionalMedNew_Temp = new Additional()
                {
                    TableName = TableName_Temp,
                    Type = Type_Temp,
                    CurrencyID = CurrancyId_Temp,
                    Value = Value_Temp
                };
                context.AddToAdditional(AdditionalMedNew_Temp);
                context.SaveChanges();
            }
        }

    }

}
